Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Query JavaScript objects with JSONPath expressions. Robust / safe JSONPath engine for Node.js.
The jsonpath npm package allows users to query and manipulate JSON documents using a query language for JSON. It provides capabilities to extract specific data from a JSON structure, similar to XPath for XML.
Query JSON
This feature allows you to query JSON for specific values using a JSONPath expression. In the code sample, it extracts the prices of books from a JSON object.
const jsonpath = require('jsonpath');
const json = { store: { book: [{ price: 10 }, { price: 20 }] } };
const prices = jsonpath.query(json, '$.store.book[*].price');
console.log(prices); // [10, 20]
Apply a callback to query results
This feature allows you to apply a callback function to each item in the result of a JSONPath query. In the code sample, it doubles the prices of books.
const jsonpath = require('jsonpath');
const json = { store: { book: [{ price: 10 }, { price: 20 }] } };
jsonpath.apply(json, '$.store.book[*].price', value => value * 2);
console.log(json); // { store: { book: [{ price: 20 }, { price: 40 }] } }
Find paths to query results
This feature retrieves the paths of query results within a JSON document. In the code sample, it finds the paths to the prices of books.
const jsonpath = require('jsonpath');
const json = { store: { book: [{ price: 10 }, { price: 20 }] } };
const paths = jsonpath.paths(json, '$.store.book[*].price');
console.log(paths); // [['$', 'store', 'book', 0, 'price'], ['$', 'store', 'book', 1, 'price']]
Parse JSONPath expressions
This feature parses a JSONPath expression and returns its structure. This can be useful for understanding or debugging complex JSONPath queries.
const jsonpath = require('jsonpath');
const expression = jsonpath.parse('$.store.book[*].price');
console.log(expression); // Outputs the parsed structure of the JSONPath expression
Lodash's get function allows you to access deep properties of an object without having to manually check for the existence of keys. It doesn't use a query language but provides a shorthand syntax for accessing nested properties. It is less powerful for complex queries compared to jsonpath.
JMESPath is a query language for JSON that allows you to extract and transform elements from a JSON document. It is similar to JSONPath but has its own syntax and additional features like custom functions and more complex expressions.
Object-path is a utility that allows you to access deep properties inside objects and arrays using a simple dot notation. It is less expressive than JSONPath and doesn't support the same query capabilities but is useful for straightforward property access.
Query JavaScript objects with JSONPath expressions. Robust / safe JSONPath engine for Node.js.
var cities = [
{ name: "London", "population": 8615246 },
{ name: "Berlin", "population": 3517424 },
{ name: "Madrid", "population": 3165235 },
{ name: "Rome", "population": 2870528 }
];
var jp = require('jsonpath');
var names = jp.query(cities, '$..name');
// [ "London", "Berlin", "Madrid", "Rome" ]
Install from npm:
$ npm install jsonpath
Here are syntax and examples adapted from Stefan Goessner's original post introducing JSONPath in 2007.
JSONPath | Description |
---|---|
$ | The root object/element |
@ | The current object/element |
. | Child member operator |
.. | Recursive descendant operator; JSONPath borrows this syntax from E4X |
* | Wildcard matching all objects/elements regardless their names |
[] | Subscript operator |
[,] | Union operator for alternate names or array indices as a set |
[start:end:step] | Array slice operator borrowed from ES4 / Python |
?() | Applies a filter (script) expression via static evaluation |
() | Script expression via static evaluation |
Given this sample data set, see example expressions below:
{
"store": {
"book": [
{
"category": "reference",
"author": "Nigel Rees",
"title": "Sayings of the Century",
"price": 8.95
}, {
"category": "fiction",
"author": "Evelyn Waugh",
"title": "Sword of Honour",
"price": 12.99
}, {
"category": "fiction",
"author": "Herman Melville",
"title": "Moby Dick",
"isbn": "0-553-21311-3",
"price": 8.99
}, {
"category": "fiction",
"author": "J. R. R. Tolkien",
"title": "The Lord of the Rings",
"isbn": "0-395-19395-8",
"price": 22.99
}
],
"bicycle": {
"color": "red",
"price": 19.95
}
}
}
Example JSONPath expressions:
JSONPath | Description |
---|---|
$.store.book[*].author | The authors of all books in the store |
$..author | All authors |
$.store.* | All things in store, which are some books and a red bicycle |
$.store..price | The price of everything in the store |
$..book[2] | The third book |
$..book[(@.length-1)] | The last book via script subscript |
$..book[-1:] | The last book via slice |
$..book[0,1] | The first two books via subscript union |
$..book[:2] | The first two books via subscript array slice |
$..book[?(@.isbn)] | Filter all books with isbn number |
$..book[?(@.price<10)] | Filter all books cheaper than 10 |
$..book[?(@.price==8.95)] | Filter all books that cost 8.95 |
$..book[?(@.price<30 && @.category=="fiction")] | Filter all fiction books cheaper than 30 |
$..* | All members of JSON structure |
Find elements in obj
matching pathExpression
. Returns an array of elements that satisfy the provided JSONPath expression, or an empty array if none were matched. Returns only first count
elements if specified.
var authors = jp.query(data, '$..author');
// [ 'Nigel Rees', 'Evelyn Waugh', 'Herman Melville', 'J. R. R. Tolkien' ]
Find paths to elements in obj
matching pathExpression
. Returns an array of element paths that satisfy the provided JSONPath expression. Each path is itself an array of keys representing the location within obj
of the matching element. Returns only first count
paths if specified.
var paths = jp.paths(data, '$..author');
// [
// ['$', 'store', 'book', 0, 'author'] },
// ['$', 'store', 'book', 1, 'author'] },
// ['$', 'store', 'book', 2, 'author'] },
// ['$', 'store', 'book', 3, 'author'] }
// ]
Find elements and their corresponding paths in obj
matching pathExpression
. Returns an array of node objects where each node has a path
containing an array of keys representing the location within obj
, and a value
pointing to the matched element. Returns only first count
nodes if specified.
var nodes = jp.nodes(data, '$..author');
// [
// { path: ['$', 'store', 'book', 0, 'author'], value: 'Nigel Rees' },
// { path: ['$', 'store', 'book', 1, 'author'], value: 'Evelyn Waugh' },
// { path: ['$', 'store', 'book', 2, 'author'], value: 'Herman Melville' },
// { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. Tolkien' }
// ]
Returns the value of the first element matching pathExpression
. If newValue
is provided, sets the value of the first matching element and returns the new value.
Returns the parent of the first matching element.
Runs the supplied function fn
on each matching element, and replaces each matching element with the return value from the function. The function accepts the value of the matching element as its only parameter. Returns matching nodes with their updated values.
var nodes = jp.apply(data, '$..author', function(value) { return value.toUpperCase() });
// [
// { path: ['$', 'store', 'book', 0, 'author'], value: 'NIGEL REES' },
// { path: ['$', 'store', 'book', 1, 'author'], value: 'EVELYN WAUGH' },
// { path: ['$', 'store', 'book', 2, 'author'], value: 'HERMAN MELVILLE' },
// { path: ['$', 'store', 'book', 3, 'author'], value: 'J. R. R. TOLKIEN' }
// ]
Parse the provided JSONPath expression into path components and their associated operations.
var path = jp.parse('$..author');
// [
// { expression: { type: 'root', value: '$' } },
// { expression: { type: 'identifier', value: 'author' }, operation: 'member', scope: 'descendant' }
// ]
Returns a path expression in string form, given a path. The supplied path may either be a flat array of keys, as returned by jp.nodes
for example, or may alternatively be a fully parsed path expression in the form of an array of path components as returned by jp.parse
.
var pathExpression = jp.stringify(['$', 'store', 'book', 0, 'author']);
// "$.store.book[0].author"
This implementation aims to be compatible with Stefan Goessner's original implementation with a few notable exceptions described below.
Script expressions (i.e, (...)
and ?(...)
) are statically evaluated via static-eval rather than using the underlying script engine directly. That means both that the scope is limited to the instance variable (@
), and only simple expressions (with no side effects) will be valid. So for example, ?(@.length>10)
will be just fine to match arrays with more than ten elements, but ?(process.exit())
will not get evaluated since process
would yield a ReferenceError
. This method is even safer than vm.runInNewContext
, since the script engine itself is more limited and entirely distinct from the one running the application code. See more details in the implementation of the evaluator.
This project uses a formal BNF grammar to parse JSONPath expressions, an attempt at reverse-engineering the intent of the original implementation, which parses via a series of creative regular expressions. The original regex approach can sometimes be forgiving for better or for worse (e.g., $['store]
=> $['store']
), and in other cases, can be just plain wrong (e.g. [
=> $
).
As a result of using a real parser and static evaluation, there are some arguable bugs in the original library that have not been carried through here:
step
arguments in slice operators may now be negative.
and @
characters not referring to instance variables$['$']
instead of $.$
)FAQs
Query JavaScript objects with JSONPath expressions. Robust / safe JSONPath engine for Node.js.
The npm package jsonpath receives a total of 1,875,256 weekly downloads. As such, jsonpath popularity was classified as popular.
We found that jsonpath demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.